/**
 * Copyright 2018 orivil.com. All rights reserved.
 * Use of this source code is governed by a MIT-style
 * license that can be found at https://mit-license.org.
 */

package sites

import (
	"net/http"
	"net/url"
	"strings"
	"io"
	"path/filepath"
	"os"
	"sync"
	"fmt"
	"time"
	"strconv"
	"gitee.com/tugoer/orivil/config"
)

type Secure func(req *http.Request)

var Cookies = initCookies()

type Cookie struct {
	Name string `json:"name"`
	Value string `json:"value"`
}

func initCookies() Secure {
	var cookies []*Cookie
	err := config.NewJsonParser("configs").ReadOrCreate("cookies", &cookies)
	if err != nil {
		panic(err)
	}
	return func(req *http.Request) {
		for _, cookie := range cookies {
			req.AddCookie(&http.Cookie{
				Name:cookie.Name,
				Value:cookie.Value,
			})
		}
	}
}

func Post(url string, secure Secure, vs url.Values) (res *http.Response, err error) {
	reader := strings.NewReader(vs.Encode())
	if req, err := http.NewRequest("POST", url, reader); err != nil {
		return nil, fmt.Errorf("url: %s \n%s\n", url, err)
	} else {
		req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
		if secure != nil {
			secure(req)
		}
		return Do(req)
	}
}

func Do(request *http.Request) (res *http.Response, err error) {
	defer func() {
		if err != nil {
			err = fmt.Errorf("url: %s\n%s\n", request.URL.String(), err)
		}
	}()
	locker.Lock()
	defer locker.Unlock()
	return http.DefaultClient.Do(request)
}

var locker = &sync.Mutex{}

func Get(url string, secure Secure, vs url.Values) (res *http.Response, err error) {
	var reader io.Reader
	if len(vs) > 0 {
		reader = strings.NewReader(vs.Encode())
	}
	if req, err := http.NewRequest("GET", url, reader); err != nil {
		return nil, fmt.Errorf("url: %s \n%s\n", url, err)
	} else {
		if secure != nil {
			secure(req)
		}
		return Do(req)
	}
}

func GetFile(URL string, secure Secure, dir string) (file string, err error) {
	u, err := url.Parse(URL)
	if err != nil {
		return "", err
	}
	// 修复某些图片 url 地址型为：http://example.com/uploads/images/dadfaljfdas.
	fname := filepath.Base(u.Path)
	if fname == "" {
		fname = strconv.FormatInt(time.Now().UnixNano(), 10)
	}
	ext := filepath.Ext(fname)
	fname = strings.TrimSuffix(fname, ext)
	if len(ext) <= 1 {
		ext = ".png"
	}
	file = filepath.Join(dir, fname+ext)
	_, err = os.Stat(file)
	// 如果文件已存在则跳过下载
	if !os.IsNotExist(err) {
		return filepath.ToSlash(file), nil
	} else {
		if res, err := Get(URL, secure, nil); err != nil {
			return "", err
		} else {
			defer res.Body.Close()
			f, err := os.OpenFile(file, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0777)
			if err != nil {
				return "", err
			}
			defer f.Close()
			_, err = io.Copy(f, res.Body)
			if err != nil {
				return "", err
			} else {
				// windows 下将 目录 images\\dsdag.png 转换为 images/dsdag.png
				return filepath.ToSlash(file), nil
			}
		}
	}
}